package com.example.demo.temple;

import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;

/**
 * @Author DuoDuo
 * @Date 2025/10/18
 * @Description Redis 服务类 提供对 Redis 数据库的操作方法
 */
@Service
public class RedisService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    // ================ 键操作 ================
    /**
     * 为指定键设置值
     */
    public void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 为指定键设置值并设置过期时间
     */

    /**
     * 为多个键值设置
     */
    public void multiSet(Map<String, Object> map) {
        redisTemplate.opsForValue().multiSet(map);
    }

    /**
     * 查看所有符合给定模式的键
     */
    public Set<String> keys(String pattern) {
        return redisTemplate.keys(pattern);
    }

    /**
     * 获取多个键值的对应值
     */
    public List<Object> multiGet(Collection<String> keys) {
        return redisTemplate.opsForValue().multiGet(keys);
    }

    /**
     * 删除指定键
     */
    public Boolean delete(String key) {
        return redisTemplate.delete(key);
    }

    /**
     * 批量删除键
     */
    public Long delete(Collection<String> keys) {
        return redisTemplate.delete(keys);
    }

    /**
     * 修改指定键名
     */
    public void rename(String oldKey, String newKey) {
        redisTemplate.rename(oldKey, newKey);
    }

    /**
     * 判断键是否存在
     */
    public Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 仅当键不存在时设置值
     */
    public Boolean setIfAbsent(String key, Object value) {
        return redisTemplate.opsForValue().setIfAbsent(key, value);
    }

    // ================ 字符串操作 ================
    /**
     * 获取指定字符串键的旧值并设置新值
     */
    public Object getAndSet(String key, Object value) {
        return redisTemplate.opsForValue().getAndSet(key, value);
    }

    /**
     * 获取指定字符串键的值
     */
    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 获取指定字符串键的值的长度
     */
    public Long strLen(String key) {
        return redisTemplate.opsForValue().size(key);
    }

    /**
     * 获取字符串键指定索引范围的值内容
     */
    public String getRange(String key, long start, long end) {
        return redisTemplate.opsForValue().get(key, start, end);
    }

    /**
     * 在指定字符串键的值末尾追加新内容
     */
    public Integer append(String key, String value) {
        return redisTemplate.opsForValue().append(key, value);
    }

    /**
     * 自增（整数）
     */
    public Long increment(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 自增（浮点数）
     */
    public Double increment(String key, double delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 覆盖字符串指定索引位置的值
     */
    public void setRange(String key, long offset, String value) {
        redisTemplate.opsForValue().set(key, value, offset);
    }

    // ================ 列表操作 ================
    /**
     * 将一个元素推入到列表左端
     */
    public Long leftPush(String key, Object value) {
        return redisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * 将多个元素推入到列表左端
     */
    public Long leftPushAll(String key, Collection<Object> values) {
        return redisTemplate.opsForList().leftPushAll(key, values);
    }

    /**
     * 将一个元素推入到列表右端
     */
    public Long rightPush(String key, Object value) {
        return redisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * 将多个元素推入到列表右端
     */
    public Long rightPushAll(String key, Collection<Object> values) {
        return redisTemplate.opsForList().rightPushAll(key, values);
    }

    /**
     * 获取列表指定索引范围内的元素
     */
    public List<Object> range(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

    /**
     * 获取列表指定索引位置上的元素
     */
    public Object index(String key, long index) {
        return redisTemplate.opsForList().index(key, index);
    }

    /**
     * 移除列表最左端的元素
     */
    public Object leftPop(String key) {
        return redisTemplate.opsForList().leftPop(key);
    }

    /**
     * 移除列表最右端的元素
     */
    public Object rightPop(String key) {
        return redisTemplate.opsForList().rightPop(key);
    }

    /**
     * 获取列表中元素的个数
     */
    public Long listSize(String key) {
        return redisTemplate.opsForList().size(key);
    }

    /**
     * 移除列表中的指定元素
     * @param key 键
     * @param count 移除数量，count>0从左到右移除count个，count<0从右到左移除count个，count=0移除所有
     * @param value 要移除的元素
     */
    public Long remove(String key, long count, Object value) {
        return redisTemplate.opsForList().remove(key, count, value);
    }


    // ================ 哈希（Hash）操作 ================
    /**
     * 向哈希表中添加一个字段和值
     * @param key 哈希表键
     * @param hashKey 字段名
     * @param value 字段值
     */
    public void hSet(String key, String hashKey, Object value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }

    /**
     * 向哈希表中批量添加字段和值
     * @param key 哈希表键
     * @param map 字段-值映射
     */
    public void hPutAll(String key, Map<Object, Object> map) {
        redisTemplate.opsForHash().putAll(key, map);
    }

    /**
     * 仅当哈希表字段不存在时添加
     * @param key 哈希表键
     * @param hashKey 字段名
     * @param value 字段值
     * @return 字段不存在并添加成功返回true，否则返回false
     */
    public Boolean hSetIfAbsent(String key, String hashKey, Object value) {
        return redisTemplate.opsForHash().putIfAbsent(key, hashKey, value);
    }

    /**
     * 获取哈希表中指定字段的值
     * @param key 哈希表键
     * @param hashKey 字段名
     * @return 字段值
     */
    public Object hGet(String key, String hashKey) {
        return redisTemplate.opsForHash().get(key, hashKey);
    }

    /**
     * 获取哈希表中所有字段和值
     * @param key 哈希表键
     * @return 字段-值映射
     */
    public Map<Object, Object> hGetAll(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 获取哈希表中所有字段名
     * @param key 哈希表键
     * @return 字段名集合
     */
    public Set<Object> hKeys(String key) {
        return redisTemplate.opsForHash().keys(key);
    }

    /**
     * 获取哈希表中所有字段值
     * @param key 哈希表键
     * @return 字段值列表
     */
    public List<Object> hValues(String key) {
        return redisTemplate.opsForHash().values(key);
    }

    /**
     * 删除哈希表中指定字段
     * @param key 哈希表键
     * @param hashKeys 字段名数组
     * @return 删除的字段数量
     */
    public Long hDelete(String key, Object... hashKeys) {
        return redisTemplate.opsForHash().delete(key, hashKeys);
    }

    /**
     * 判断哈希表中是否存在指定字段
     * @param key 哈希表键
     * @param hashKey 字段名
     * @return 是否存在
     */
    public Boolean hHasKey(String key, String hashKey) {
        return redisTemplate.opsForHash().hasKey(key, hashKey);
    }

    /**
     * 哈希表字段值自增
     * @param key 哈希表键
     * @param hashKey 字段名
     * @param delta 增量
     * @return 自增后的值
     */
    public Long hIncrement(String key, String hashKey, long delta) {
        return redisTemplate.opsForHash().increment(key, hashKey, delta);
    }

    /**
     * 哈希表字段值自增（浮点数）
     * @param key 哈希表键
     * @param hashKey 字段名
     * @param delta 增量
     * @return 自增后的值
     */
    public Double hIncrement(String key, String hashKey, double delta) {
        return redisTemplate.opsForHash().increment(key, hashKey, delta);
    }

    /**
     * 获取哈希表中字段的数量
     * @param key 哈希表键
     * @return 字段数量
     */
    public Long hSize(String key) {
        return redisTemplate.opsForHash().size(key);
    }


    // ================ 集合（Set）操作 ================
    /**
     * 向集合中添加一个或多个元素
     * @param key 集合键
     * @param values 元素数组
     * @return 添加成功的元素数量（已存在的元素不重复添加）
     */
    public Long sAdd(String key, Object... values) {
        return redisTemplate.opsForSet().add(key, values);
    }

    /**
     * 获取集合中所有元素
     * @param key 集合键
     * @return 元素集合
     */
    public Set<Object> sMembers(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * 判断元素是否在集合中
     * @param key 集合键
     * @param value 元素
     * @return 是否存在
     */
    public Boolean sIsMember(String key, Object value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }

    /**
     * 获取集合的大小（元素数量）
     * @param key 集合键
     * @return 元素数量
     */
    public Long sSize(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    /**
     * 从集合中移除一个或多个元素
     * @param key 集合键
     * @param values 元素数组
     * @return 移除成功的元素数量
     */
    public Long sRemove(String key, Object... values) {
        return redisTemplate.opsForSet().remove(key, values);
    }

    /**
     * 随机从集合中移除并返回一个元素
     * @param key 集合键
     * @return 被移除的元素
     */
    public Object sPop(String key) {
        return redisTemplate.opsForSet().pop(key);
    }

    /**
     * 随机从集合中获取指定数量的元素（不会移除元素）
     * @param key 集合键
     * @param count 获取数量
     * @return 元素列表
     */
    public List<Object> sRandomMembers(String key, long count) {
        return redisTemplate.opsForSet().randomMembers(key, count);
    }

    /**
     * 计算两个集合的差集（key1中有而key2中没有的元素）
     * @param key1 集合1键
     * @param key2 集合2键
     * @return 差集元素集合
     */
    public Set<Object> sDifference(String key1, String key2) {
        return redisTemplate.opsForSet().difference(key1, key2);
    }

    /**
     * 计算两个集合的交集（key1和key2中都有的元素）
     * @param key1 集合1键
     * @param key2 集合2键
     * @return 交集元素集合
     */
    public Set<Object> sIntersect(String key1, String key2) {
        return redisTemplate.opsForSet().intersect(key1, key2);
    }

    /**
     * 计算两个集合的并集（key1和key2中所有元素，去重）
     * @param key1 集合1键
     * @param key2 集合2键
     * @return 并集元素集合
     */
    public Set<Object> sUnion(String key1, String key2) {
        return redisTemplate.opsForSet().union(key1, key2);
    }


    // ================ 有序集合（ZSet）操作 ================
    /**
     * 向有序集合中添加一个元素（带分数）
     * @param key 有序集合键
     * @param value 元素
     * @param score 分数（用于排序）
     * @return 添加成功返回true，已存在则更新分数并返回false
     */
    public Boolean zAdd(String key, Object value, double score) {
        return redisTemplate.opsForZSet().add(key, value, score);
    }

    /**
     * 向有序集合中批量添加元素（带分数）
     * @param key 有序集合键
     * @param tuples 元素-分数对集合
     * @return 添加成功的元素数量
     */
    public Long zAdd(String key, Set<ZSetOperations.TypedTuple<Object>> tuples) {
        return redisTemplate.opsForZSet().add(key, tuples);
    }

    /**
     * 移除有序集合中的一个或多个元素
     * @param key 有序集合键
     * @param values 元素数组
     * @return 移除成功的元素数量
     */
    public Long zRemove(String key, Object... values) {
        return redisTemplate.opsForZSet().remove(key, values);
    }

    /**
     * 为有序集合中指定元素的分数增加增量
     * @param key 有序集合键
     * @param value 元素
     * @param delta 增量（可正可负）
     * @return 增量后的分数
     */
    public Double zIncrementScore(String key, Object value, double delta) {
        return redisTemplate.opsForZSet().incrementScore(key, value, delta);
    }

    /**
     * 获取元素在有序集合中的排名（按分数升序，从0开始）
     * @param key 有序集合键
     * @param value 元素
     * @return 排名（-1表示元素不存在）
     */
    public Long zRank(String key, Object value) {
        return redisTemplate.opsForZSet().rank(key, value);
    }

    /**
     * 获取元素在有序集合中的排名（按分数降序，从0开始）
     * @param key 有序集合键
     * @param value 元素
     * @return 排名（-1表示元素不存在）
     */
    public Long zReverseRank(String key, Object value) {
        return redisTemplate.opsForZSet().reverseRank(key, value);
    }

    /**
     * 获取有序集合中指定排名范围的元素（按分数升序）
     * @param key 有序集合键
     * @param start 起始排名（0开始）
     * @param end 结束排名（-1表示最后一个）
     * @return 元素集合
     */
    public Set<Object> zRange(String key, long start, long end) {
        return redisTemplate.opsForZSet().range(key, start, end);
    }

    /**
     * 获取有序集合中指定排名范围的元素（带分数，按分数升序）
     * @param key 有序集合键
     * @param start 起始排名
     * @param end 结束排名
     * @return 元素-分数对集合
     */
    public Set<ZSetOperations.TypedTuple<Object>> zRangeWithScores(String key, long start, long end) {
        return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
    }

    /**
     * 获取有序集合中指定排名范围的元素（按分数降序）
     * @param key 有序集合键
     * @param start 起始排名
     * @param end 结束排名
     * @return 元素集合
     */
    public Set<Object> zReverseRange(String key, long start, long end) {
        return redisTemplate.opsForZSet().reverseRange(key, start, end);
    }

    /**
     * 获取有序集合中指定分数范围的元素（按分数升序）
     * @param key 有序集合键
     * @param min 最小分数
     * @param max 最大分数
     * @return 元素集合
     */
    public Set<Object> zRangeByScore(String key, double min, double max) {
        return redisTemplate.opsForZSet().rangeByScore(key, min, max);
    }

    /**
     * 移除有序集合中指定排名范围的元素
     * @param key 有序集合键
     * @param start 起始排名
     * @param end 结束排名
     * @return 移除的元素数量
     */
    public Long zRemoveRange(String key, long start, long end) {
        return redisTemplate.opsForZSet().removeRange(key, start, end);
    }

    /**
     * 移除有序集合中指定分数范围的元素
     * @param key 有序集合键
     * @param min 最小分数
     * @param max 最大分数
     * @return 移除的元素数量
     */
    public Long zRemoveRangeByScore(String key, double min, double max) {
        return redisTemplate.opsForZSet().removeRangeByScore(key, min, max);
    }

    /**
     * 获取有序集合中元素的数量
     * @param key 有序集合键
     * @return 元素数量
     */
    public Long zSize(String key) {
        return redisTemplate.opsForZSet().size(key);
    }

    /**
     * 获取有序集合中指定分数范围内的元素数量
     * @param key 有序集合键
     * @param min 最小分数
     * @param max 最大分数
     * @return 元素数量
     */
    public Long zCount(String key, double min, double max) {
        return redisTemplate.opsForZSet().count(key, min, max);
    }

    /**
     * 获取有序集合中指定元素的分数
     * @param key 有序集合键
     * @param value 元素
     * @return 分数（null表示元素不存在）
     */
    public Double zScore(String key, Object value) {
        return redisTemplate.opsForZSet().score(key, value);
    }

}